package com.sunday.redis.study;//package com.sunday.leaf.study;
//
//import io.lettuce.core.resource.ClientResources;
//import io.lettuce.core.resource.DefaultClientResources;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
//import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
//import org.springframework.beans.factory.config.ConstructorArgumentValues;
//import org.springframework.beans.factory.support.AbstractBeanDefinition;
//import org.springframework.beans.factory.support.BeanDefinitionBuilder;
//import org.springframework.beans.factory.support.BeanDefinitionRegistry;
//import org.springframework.beans.factory.support.GenericBeanDefinition;
//import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
//import org.springframework.boot.context.properties.bind.Binder;
//import org.springframework.context.EnvironmentAware;
//import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
//import org.springframework.core.env.Environment;
//import org.springframework.core.type.AnnotationMetadata;
//import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
//import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
//import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.util.StringUtils;
//
//import java.util.Map;
//import java.util.NoSuchElementException;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.function.Supplier;
//
//
///**
// * Binder 负责处理对象与多个ConfigurationPropertySource（属性）之间的绑定
// *
// * EnvironmentAware 凡注册到Spring容器内的bean，实现了EnvironmentAware接口重写setEnvironment方法后，
// * 在工程启动时可以获得application.properties的配置文件配置的属性值。
// *
// * ImportBeanDefinitionRegistrar 类只能通过其他类@Import的方式来加载，通常是启动类或配置类。
// * 使用@Import，如果括号中的类是ImportBeanDefinitionRegistrar的实现类，则会调用接口方法，将其中要注册的类注册成bean。
// * 实现该接口的类拥有注册bean的能力。
// */
//@Slf4j
//public class MultiRedisRegister extends MultiRedisConnectionConfiguration implements EnvironmentAware, ImportBeanDefinitionRegistrar {
//
//    private static Map<String, LettuceConnectionFactory> registerBean = new ConcurrentHashMap<>();
//    private final String PROPERTIES_PREFIX = "sunday";
//    private Environment env;
//    private Binder binder;
//
//    @Override
//    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//        // get all redis config
////        Map<String, Map> multipleRedis;
//        MultiRedisProperties multipleRedis;
////        log.info("{}",this.env.containsProperty(PROPERTIES_PREFIX));
//        try {
//            multipleRedis = binder.bind(PROPERTIES_PREFIX, MultiRedisProperties.class).get();
//        } catch (NoSuchElementException e) {
//            log.warn("Failed to configure sunday redis: 'sunday.redis' attribute is not specified and no embedded redis could be configured.");
//            return;
//        }
//        boolean onPrimary = true;
//
//        for(String key : multipleRedis.getRedis().keySet()){
//            RedisProperties redisProperties = multipleRedis.getRedis().get(key);
//
//            //LettuceConnectionFactory
//            Supplier<LettuceConnectionFactory> lettuceConnectionFactorySupplier = () -> {
//                LettuceConnectionFactory factory = registerBean.get(key + "LettuceConnectionFactory");
//                if (factory != null) {
//                    return factory;
//                }
//                LettuceClientConfiguration clientConfig = getLettuceClientConfiguration(
//                        DefaultClientResources.create(),
//                        redisProperties);
//                factory = createLettuceConnectionFactory(clientConfig,redisProperties);
//                registerBean.put(key + "LettuceConnectionFactory", factory);
//                return factory;
//            };
//            LettuceConnectionFactory lettuceConnectionFactory = lettuceConnectionFactorySupplier.get();
//            //创建bean实例 并附带初始化参数
//            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(LettuceConnectionFactory.class,lettuceConnectionFactorySupplier);
//            AbstractBeanDefinition factoryBean = builder.getRawBeanDefinition();
//            //该bean是否为主要自动装配候选对象。如果该值恰好是{@code true}，用于多个bean中的一个*匹配候选人，它将成为决定胜负的关键因素。
//            factoryBean.setPrimary(onPrimary);
//            //手动向Spring容器中注入Bean
//            registry.registerBeanDefinition(key + "LettuceConnectionFactory", factoryBean);
//
//            // StringRedisTemplate
//            GenericBeanDefinition stringRedisTemplate = new GenericBeanDefinition();
//            stringRedisTemplate.setBeanClass(StringRedisTemplate.class);
//            ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
//            constructorArgumentValues.addIndexedArgumentValue(0, lettuceConnectionFactory);
//            stringRedisTemplate.setConstructorArgumentValues(constructorArgumentValues);
//            stringRedisTemplate.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
//            registry.registerBeanDefinition(key + "StringRedisTemplate", stringRedisTemplate);
//
//            // RedisTemplate
//            GenericBeanDefinition redisTemplate = new GenericBeanDefinition();
//            redisTemplate.setBeanClass(RedisTemplate.class);
//            redisTemplate.getPropertyValues().add("connectionFactory", lettuceConnectionFactory);
//            redisTemplate.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
//            registry.registerBeanDefinition(key + "RedisTemplate", redisTemplate);
//
//            log.info("Registration redis ({}) , database ({}) !", key,redisProperties.getDatabase());
//            if (onPrimary) {
//                onPrimary = false;
//            }
//
//        }
//        log.info("{}","Registration redis completed !");
//    }
//
//    @Override
//    public void setEnvironment(Environment environment) {
//        this.env = environment;
//        // bing binder
//        binder = Binder.get(this.env);
//    }
//
//    private LettuceConnectionFactory createLettuceConnectionFactory(
//            LettuceClientConfiguration clientConfiguration, RedisProperties redisProperties) {
//        if (getSentinelConfig(redisProperties) != null) {
//            return new LettuceConnectionFactory(getSentinelConfig(redisProperties), clientConfiguration);
//        }
//        if (getClusterConfiguration(redisProperties) != null) {
//            return new LettuceConnectionFactory(getClusterConfiguration(redisProperties), clientConfiguration);
//        }
//        return new LettuceConnectionFactory(getStandaloneConfig(redisProperties), clientConfiguration);
//    }
//
//    private LettuceClientConfiguration getLettuceClientConfiguration(
//            ClientResources clientResources, RedisProperties redisProperties) {
//        LettuceClientConfiguration.LettuceClientConfigurationBuilder builder = createBuilder(redisProperties.getLettuce().getPool());
//        applyProperties(builder,redisProperties);
//        if (StringUtils.hasText(redisProperties.getUrl())) {
//            ConnectionInfo connectionInfo = parseUrl(redisProperties.getUrl());
//            if (connectionInfo.isUseSsl()) {
//                builder.useSsl();
//            }
//        }
//        builder.clientResources(clientResources);
//        return builder.build();
//    }
//
//
//    private LettuceClientConfiguration.LettuceClientConfigurationBuilder applyProperties(
//            LettuceClientConfiguration.LettuceClientConfigurationBuilder builder,
//            RedisProperties redisProperties) {
//        if (redisProperties.isSsl()) {
//            builder.useSsl();
//        }
//        if (redisProperties.getTimeout() != null) {
//            builder.commandTimeout(redisProperties.getTimeout());
//        }
//        if (redisProperties.getLettuce() != null) {
//            RedisProperties.Lettuce lettuce = redisProperties.getLettuce();
//            if (lettuce.getShutdownTimeout() != null
//                    && !lettuce.getShutdownTimeout().isZero()) {
//                builder.shutdownTimeout(
//                        redisProperties.getLettuce().getShutdownTimeout());
//            }
//        }
//        return builder;
//    }
//
//    private LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool pool) {
//        if (pool == null) {
//            return LettuceClientConfiguration.builder();
//        }
//        return new PoolBuilderFactory().createBuilder(pool);
//    }
//
//    /**
//     * Inner class to allow optional commons-pool2 dependency.
//     */
//    private static class PoolBuilderFactory {
//
//        public LettuceClientConfiguration.LettuceClientConfigurationBuilder createBuilder(RedisProperties.Pool properties) {
//            return LettucePoolingClientConfiguration.builder()
//                    .poolConfig(getPoolConfig(properties));
//        }
//
//        private GenericObjectPoolConfig<?> getPoolConfig(RedisProperties.Pool properties) {
//            GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
//            config.setMaxTotal(properties.getMaxActive());
//            config.setMaxIdle(properties.getMaxIdle());
//            config.setMinIdle(properties.getMinIdle());
//            if (properties.getMaxWait() != null) {
//                config.setMaxWaitMillis(properties.getMaxWait().toMillis());
//            }
//            return config;
//        }
//
//    }
//
//}
